home *** CD-ROM | disk | FTP | other *** search
/ Aminet 22 / Aminet 22 (1997)(GTI - Schatztruhe)[!][Dec 1997].iso / Aminet / util / blank / BeyondTheDark.lha / BeyondTheDark / Developer / Source / Toaster / Toaster.c < prev    next >
C/C++ Source or Header  |  1997-04-20  |  15KB  |  572 lines

  1.  
  2. #include <exec/memory.h>
  3. #include <exec/execbase.h>
  4. #include <graphics/gfxbase.h>
  5. #include <intuition/intuitionbase.h>
  6. #include <libraries/iffparse.h>
  7. #include <utility/tagitem.h>
  8. #include <cybergraphics/cybergraphics.h>
  9.  
  10. #define __USE_SYSBASE 42
  11.  
  12. #include <proto/cybergraphics.h>
  13. #include <proto/exec.h>
  14. #include <proto/graphics.h>
  15. #include <proto/intuition.h>
  16. #include <proto/utility.h>
  17.  
  18. #include <string.h>
  19.  
  20. #include "btd.h"
  21.  
  22. struct GfxBase *GfxBase;
  23. struct IntuitionBase *IntuitionBase;
  24. struct Library *UtilityBase,*CyberGfxBase;
  25.  
  26. #define TPTAG(o) (BTD_Client+(o))
  27.  
  28. #define TP_Toasters TPTAG(0)
  29.  
  30. #define MAX_TOASTERS  20L
  31. #define DEF_TOASTERS   2L
  32.  
  33. #define NUM_IMAGES 4
  34.  
  35. #define IMAGE_WIDTH  64
  36. #define IMAGE_HEIGHT 64
  37. #define IMAGE_WIDBUF (IMAGE_WIDTH+20)
  38. #define IMAGE_HEIBUF (IMAGE_HEIGHT+20)
  39.  
  40. extern UBYTE *BytePackedFrames[];
  41.  
  42. #define ABS(x)   __builtin_abs(x)
  43. #define MIN(a,b) __builtin_min(a,b)
  44. #define MAX(a,b) __builtin_max(a,b)
  45.  
  46. #define NUM_COLORS 16
  47. #define NUM_PHASES ((NUM_IMAGES*2)-2)
  48.  
  49. struct BTDInteger ToasterIntParams[] =
  50.  {
  51.   TP_Toasters,"Toasters",BTDPT_INTEGER,DEF_TOASTERS,1L,MAX_TOASTERS,TRUE,
  52.  };
  53.  
  54. struct BTDNode *ToasterParams[] =
  55.  {
  56.   &ToasterIntParams[0].BI_Node,
  57.   NULL
  58.  };
  59.  
  60. struct BTDInfo ToasterInfo =
  61.  {
  62.   BTDI_Revision,MAKE_ID('T','O','S','T'),
  63.   "Toaster","The Must of Blankers","Markus Illenseer and Matthias Scheler",
  64.   ToasterParams
  65.  };
  66.  
  67. struct IToaster
  68.  {
  69.   LONG delay;
  70.   LONG x, y;
  71.   LONG old_x,old_y;
  72.   LONG xspeed,yspeed;
  73.   LONG phase;
  74.   LONG xcol,ycol;
  75.  };
  76.  
  77. struct Toasters /* structure for a swarm, including the wasp */
  78.  {
  79.   struct BTDDrawInfo *BTDDrawInfo;
  80.   WORD Width;   /* Width and */
  81.   WORD Height;  /* Height of the used area */
  82.   WORD NumToaster; /* total number of the Toasters*/
  83.   struct IToaster *Toasters;
  84.   struct ToasterImage *Images[NUM_PHASES];
  85.   LONG RandN,RandF,RandI;
  86.  };
  87.  
  88. UBYTE CMap[(NUM_COLORS-1)*3] =
  89.  {
  90.   0x33,0x33,0x33,0x55,0x55,0x55,0x88,0x55,0x22,0x66,0x66,0x66,0x77,0x77,0x44,
  91.   0x55,0x55,0x66,0xEE,0x55,0x22,0x88,0x88,0x88,0x99,0x99,0x99,0xBB,0xBB,0xBB,
  92.   0xCC,0xCC,0xCC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0xEE,0xEE,0xFF,0xFF,0xFF
  93.  };
  94.  
  95. struct ToasterImage
  96.  {
  97.   WORD ti_Width,ti_Height;
  98.   struct BitMap ti_BitMap;
  99.   UBYTE *ti_ChunkyData;
  100.  };
  101.  
  102. /* library stuff */
  103.  
  104. char MyBlankerName[] = "toaster.btd";
  105. char MyBlankerID[]   = "Toaster Blanker V" VERSION "." REVISION " for BTD";
  106.  
  107. LONG MyBlankerLibInit(void)
  108.  
  109. {
  110.  if (GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",37L))
  111.   {
  112.    if (IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",37L))
  113.     {
  114.      if (UtilityBase=OpenLibrary("utility.library",37L))
  115.       {
  116.        CyberGfxBase=OpenLibrary("cybergraphics.library",40L);
  117.        return TRUE;
  118.       }
  119.  
  120.      CloseLibrary (&IntuitionBase->LibNode);
  121.     }
  122.    CloseLibrary (&GfxBase->LibNode);
  123.   }
  124.  return FALSE;
  125. }
  126.  
  127. void MyBlankerLibFree(void)
  128.  
  129. {
  130.  if (CyberGfxBase) CloseLibrary (CyberGfxBase);
  131.  CloseLibrary (UtilityBase);
  132.  CloseLibrary (&IntuitionBase->LibNode);
  133.  CloseLibrary (&GfxBase->LibNode);
  134. }
  135.  
  136. /* random generator */
  137.  
  138. void __regargs InitRandom(struct Toasters *TP,ULONG Instance)
  139.  
  140. {
  141.  ULONG Time[2];
  142.  
  143.  CurrentTime (&Time[0],&Time[1]);
  144.  TP->RandN=(LONG)Time[0];
  145.  
  146.  if (Time[1]<1024L) Time[1]|=1;
  147.  else Time[1]>>=10;
  148.  Time[1]^=Instance;
  149.  
  150.  TP->RandF=4*Time[1]+1;
  151.  TP->RandI=2*Time[1]+1;
  152. }
  153.  
  154. WORD __regargs Random(struct Toasters *TP,WORD Max)
  155.  
  156. {
  157.  TP->RandN=TP->RandF*TP->RandN+TP->RandI;
  158.  if (TP->RandN<0L) TP->RandN=-TP->RandN;
  159.  
  160.  return (WORD)(TP->RandN%Max);
  161. }
  162.  
  163. /* implementation of library functions */
  164.  
  165. struct BTDInfo *QueryMyBlanker(void)
  166.  
  167. {
  168.  return &ToasterInfo;
  169. }
  170.  
  171. void __regargs DeleteToasterImage(struct ToasterImage *TI)
  172.  
  173. {
  174.  if (TI->ti_ChunkyData) FreeVec (TI->ti_ChunkyData);
  175.  else
  176.   {
  177.    ULONG Index,Size;
  178.  
  179.    Size=TI->ti_BitMap.BytesPerRow*TI->ti_BitMap.Rows;
  180.    for (Index=0L; Index<TI->ti_BitMap.Depth; Index++)
  181.     FreeMem (TI->ti_BitMap.Planes[Index],Size);
  182.   }
  183.  
  184.  FreeVec (TI);
  185. }
  186.  
  187. struct ToasterImage __regargs *ConvertToasterImage(UBYTE *From,UWORD *RemapTab,
  188.                                                    struct RastPort *RastPort,LONG Chunky)
  189.  
  190. {
  191.  struct ToasterImage *Target;
  192.  
  193.  if ((Target=AllocVec(sizeof(struct ToasterImage),MEMF_PUBLIC))==NULL) return NULL;
  194.  
  195.  Target->ti_Width=IMAGE_WIDTH;
  196.  Target->ti_Height=IMAGE_HEIGHT;
  197.  
  198.  if (Chunky)
  199.   {
  200.    ULONG Pixels;
  201.  
  202.    Pixels=Target->ti_Width*Target->ti_Height;
  203.    if (Target->ti_ChunkyData=AllocVec(Pixels,MEMF_PUBLIC))
  204.     {
  205.      UBYTE *To,Nibble;
  206.  
  207.      To=Target->ti_ChunkyData;
  208.      while (Pixels)
  209.       {
  210.        Nibble=*From>>4;
  211.        if (Nibble) *To++=RemapTab[Nibble];
  212.        else *To++=BTD_BgPen;
  213.  
  214.        Nibble=(*From++)&15;
  215.        if (Nibble) *To++=RemapTab[Nibble];
  216.        else *To++=BTD_BgPen;
  217.  
  218.        Pixels-=2L;
  219.       }
  220.     }
  221.    else
  222.     {
  223.      FreeVec (Target);
  224.      Target=NULL;
  225.     }
  226.   }
  227.  else
  228.   {
  229.    ULONG Index,Size;
  230.    LONG Depth,X,Y;
  231.  
  232.    Target->ti_ChunkyData=NULL;
  233.  
  234.    Depth=1L;
  235.    for (Index=1L; Index<NUM_COLORS; Index++)
  236.     while (RemapTab[Index]>=(1L<<Depth)) Depth++;
  237.  
  238.    InitBitMap (&Target->ti_BitMap,Depth,Target->ti_Width,Target->ti_Height);
  239.  
  240.    Size=Target->ti_BitMap.BytesPerRow*Target->ti_BitMap.Rows;
  241.    for (Index=0L; Index<Target->ti_BitMap.Depth; Index++)
  242.     if ((Target->ti_BitMap.Planes[Index]=AllocMem(Size,MEMF_CHIP|MEMF_CLEAR))==NULL)
  243.      {
  244.       while (Index--) FreeMem (Target->ti_BitMap.Planes[Index],Size);
  245.       FreeVec (Target);
  246.       return NULL;
  247.      }
  248.  
  249.    RastPort->BitMap=&Target->ti_BitMap;
  250.  
  251.    if (GfxBase->LibNode.lib_Version>=40)
  252.     {
  253.      ULONG Pixels;
  254.      UBYTE *Data;
  255.  
  256.      Pixels=Target->ti_Width*Target->ti_Height;
  257.      if (Data=AllocVec(Pixels,MEMF_PUBLIC))
  258.       {
  259.        UBYTE *To,Nibble;
  260.  
  261.        To=Data;
  262.        while (Pixels)
  263.         {
  264.          Nibble=*From>>4;
  265.          if (Nibble) *To++=RemapTab[Nibble];
  266.          else *To++=BTD_BgPen;
  267.  
  268.          Nibble=(*From++)&15;
  269.          if (Nibble) *To++=RemapTab[Nibble];
  270.          else *To++=BTD_BgPen;
  271.  
  272.          Pixels-=2L;
  273.         }
  274.        WriteChunkyPixels (RastPort,0,0,Target->ti_Width-1,Target->ti_Height-1,Data,IMAGE_WIDTH);
  275.  
  276.        FreeVec (Data);
  277.        return Target;
  278.       }
  279.     }
  280.  
  281.    for (Y=0L; Y<Target->ti_Height; Y++)
  282.     for (X=0L; X<Target->ti_Width; X+=2)
  283.      {
  284.       UBYTE Nibble;
  285.  
  286.       Nibble=*From>>4;
  287.       if (Nibble)
  288.        {         SetAPen (RastPort,RemapTab[Nibble]);
  289.         (void)WritePixel(RastPort,X,Y);
  290.        }
  291.  
  292.       Nibble=(*From++)&15;
  293.       if (Nibble)
  294.        {         SetAPen (RastPort,RemapTab[Nibble]);
  295.         (void)WritePixel(RastPort,X+1,Y);
  296.        }
  297.      } 
  298.   } 
  299.  
  300.  return Target;
  301. }
  302.  
  303. void __regargs SafeEraseRect(struct BTDDrawInfo *BTDDrawInfo,
  304.                              LONG Left,LONG Top,
  305.                              LONG Right,LONG Bottom)
  306.  
  307. {
  308.  if ((Left<BTDDrawInfo->BDI_Width)&&(Right>=MAX(Left,0L))&&
  309.      (Top<BTDDrawInfo->BDI_Height)&&(Bottom>=MAX(Top,0L)))
  310.   EraseRect (BTDDrawInfo->BDI_RPort,
  311.              BTDDrawInfo->BDI_Left+MAX(Left,0L),
  312.              BTDDrawInfo->BDI_Top+MAX(Top,0L),
  313.              BTDDrawInfo->BDI_Left+MIN(Right,BTDDrawInfo->BDI_Width-1),
  314.              BTDDrawInfo->BDI_Top+MIN(Bottom,BTDDrawInfo->BDI_Height-1));
  315. }
  316.  
  317. void __regargs DrawToasterImage(struct BTDDrawInfo *BTDDrawInfo,
  318.                                struct ToasterImage *TI,
  319.                                LONG XPos,LONG YPos)
  320.  
  321. {
  322.  LONG Left,Top,Right,Bottom;
  323.  
  324.  Left=MAX(XPos,0L);
  325.  Top=MAX(YPos,0L);
  326.  Right=MIN(XPos+TI->ti_Width,BTDDrawInfo->BDI_Width);
  327.  Bottom=MIN(YPos+TI->ti_Height,BTDDrawInfo->BDI_Height);
  328.  
  329.  if ((Left<Right)&&(Top<Bottom))
  330.   if (TI->ti_ChunkyData)
  331.    (void)WritePixelArray(TI->ti_ChunkyData,Left-XPos,Top-YPos,TI->ti_Width,
  332.                          BTDDrawInfo->BDI_RPort,Left,Top,
  333.                          Right-Left,Bottom-Top,RECTFMT_LUT8);
  334.   else
  335.    BltBitMapRastPort (&TI->ti_BitMap,Left-XPos,Top-YPos,
  336.                       BTDDrawInfo->BDI_RPort,Left,Top,
  337.                       Right-Left,Bottom-Top,0xC0);
  338. }
  339.  
  340. LONG __regargs TestExtent(struct Toasters *TP,LONG Start,LONG Me,LONG x,LONG y)
  341.  
  342. {
  343.  LONG Index;
  344.   
  345.  for (Index=Start; Index<TP->NumToaster; Index++)
  346.   if ((Index!=Me)&&!TP->Toasters[Index].delay&&
  347.       (ABS(x-TP->Toasters[Index].x)<IMAGE_WIDBUF)&&
  348.       (ABS(y-TP->Toasters[Index].y)<IMAGE_HEIBUF)) return Index;
  349.   
  350.  return -1L;
  351. }
  352.  
  353. BOOL __regargs FindLaunchPos(struct Toasters *TP,LONG Index)
  354.  
  355. {
  356.  LONG x,y;
  357.   
  358.  x=TP->Width-IMAGE_WIDTH;
  359.  y=IMAGE_HEIGHT+Random(TP,TP->Height);
  360.   
  361.  FOREVER
  362.   {
  363.    if (x<=(2*IMAGE_WIDTH)) return FALSE;
  364.     
  365.    if (TestExtent(TP,0,Index,x,y)==-1L)
  366.     {
  367.      TP->Toasters[Index].x=TP->Toasters[Index].old_x=x;
  368.      TP->Toasters[Index].y=TP->Toasters[Index].old_y=y;
  369.      TP->Toasters[Index].xspeed=Random(TP,3)+1;
  370.      TP->Toasters[Index].yspeed=Random(TP,2)+1;
  371.      TP->Toasters[Index].phase=Random(TP,NUM_IMAGES);
  372.  
  373.      return TRUE;
  374.     }
  375.     
  376.    if (y>(-IMAGE_HEIGHT)) y-=IMAGE_HEIGHT;
  377.    else x-=IMAGE_WIDTH;
  378.   }
  379. }
  380.  
  381. LONG __regargs ActXSpeed(struct Toasters *TP,LONG Index)
  382.  
  383. {
  384.  if (TP->Toasters[Index].xcol==-1L) return TP->Toasters[Index].xspeed;
  385.  else return ActXSpeed(TP,TP->Toasters[Index].xcol);
  386. }
  387.  
  388. LONG __regargs ActYSpeed(struct Toasters *TP,LONG Index)
  389.  
  390. {
  391.  if (TP->Toasters[Index].ycol==-1L) return TP->Toasters[Index].yspeed;
  392.  else return ActXSpeed(TP,TP->Toasters[Index].ycol);
  393. }
  394.  
  395. void EndMyBlanker(struct Toasters *TP)
  396.  
  397. {
  398.  ULONG Index;
  399.  
  400.  for (Index=0L; Index<NUM_IMAGES; Index++)
  401.   if (TP->Images[Index]) DeleteToasterImage (TP->Images[Index]);
  402.  FreeVec (TP);
  403. }
  404.  
  405. struct Toasters *InitMyBlanker(struct TagItem *TagList)
  406.  
  407. {
  408.  struct BTDDrawInfo *BTDDrawInfo;
  409.  ULONG *Error,Dummy,Instance,Index;
  410.  LONG Chunky,NumToaster;
  411.  struct Toasters *TP;
  412.  struct RastPort TempRastPort;
  413.  UBYTE *CMapPtr;
  414.  
  415.  if ((BTDDrawInfo=(struct BTDDrawInfo *)
  416.                    GetTagData(BTD_DrawInfo,NULL,TagList))==NULL) return NULL;
  417.  Error=(ULONG *)GetTagData(BTD_Error,(ULONG)&Dummy,TagList);
  418.  
  419.  Chunky=(CyberGfxBase==NULL)?FALSE:GetCyberMapAttr(BTDDrawInfo->BDI_RPort->BitMap,CYBRMATTR_ISCYBERGFX);
  420.  Instance=GetTagData(BTD_Instance,0L,TagList);
  421.  NumToaster=GetTagData(TP_Toasters,DEF_TOASTERS,TagList);
  422.  
  423.  if ((TP=AllocVec(sizeof(struct Toasters)+sizeof(struct IToaster)*NumToaster,MEMF_PUBLIC|MEMF_CLEAR))==NULL)
  424.   {
  425.    *Error=BTDERR_Memory;
  426.    return NULL;
  427.   }
  428.  TP->Toasters=(struct IToaster *)&TP[1];
  429.  
  430.  InitRastPort (&TempRastPort);
  431.  for (Index=0L; Index<NUM_IMAGES; Index++)
  432.   if ((TP->Images[Index]=ConvertToasterImage(BytePackedFrames[Index],
  433.                                              BTDDrawInfo->BDI_Pens-1,
  434.                                              &TempRastPort,Chunky))==NULL)
  435.    {
  436.     EndMyBlanker (TP);
  437.  
  438.     *Error=BTDERR_Memory;
  439.     return NULL;
  440.    }
  441.  for (; Index<NUM_PHASES; Index++)
  442.   TP->Images[Index]=TP->Images[NUM_PHASES-Index];
  443.  
  444.  TP->BTDDrawInfo=BTDDrawInfo;
  445.  TP->Width=BTDDrawInfo->BDI_Width;
  446.  TP->Height=BTDDrawInfo->BDI_Height;
  447.  TP->NumToaster=NumToaster;
  448.  
  449.  InitRandom (TP,Instance);
  450.  
  451.  for (Index=0L, CMapPtr=CMap; Index<(NUM_COLORS-1L); Index++)
  452.   {
  453.    BTDDrawInfo->BDI_Red[BTDDrawInfo->BDI_Pens[Index]]=*CMapPtr++;
  454.    BTDDrawInfo->BDI_Green[BTDDrawInfo->BDI_Pens[Index]]=*CMapPtr++;
  455.    BTDDrawInfo->BDI_Blue[BTDDrawInfo->BDI_Pens[Index]]=*CMapPtr++;
  456.    BTDDrawInfo->BDI_Changed[BTDDrawInfo->BDI_Pens[Index]]=TRUE;
  457.   }
  458.  
  459.  for (Index=0L; Index<NumToaster; Index++)
  460.   if (!FindLaunchPos(TP,Index)) TP->Toasters[Index].delay=30;
  461.  
  462.  return TP;
  463. }
  464.  
  465. void AnimMyBlanker(struct Toasters *TP)
  466.  
  467. {
  468.  struct BTDDrawInfo *BTDDrawInfo;
  469.  LONG i,j;
  470.  
  471.  BTDDrawInfo=TP->BTDDrawInfo;
  472.  
  473.  for (i=0; i<TP->NumToaster; i++)
  474.   if (TP->Toasters[i].delay==0L)
  475.    {
  476.     TP->Toasters[i].old_x=TP->Toasters[i].x;
  477.     TP->Toasters[i].old_y=TP->Toasters[i].y;
  478.     TP->Toasters[i].x-=TP->Toasters[i].xspeed;
  479.     TP->Toasters[i].y+=TP->Toasters[i].yspeed;
  480.     TP->Toasters[i].xcol=-1;
  481.     TP->Toasters[i].ycol=-1;
  482.    }
  483.  
  484.  for (i=0; i<TP->NumToaster; i++)
  485.   {
  486.    if (TP->Toasters[i].delay==0L)
  487.     {
  488.      j=-1;
  489.      while ((j=TestExtent(TP,j+1,i,TP->Toasters[i].x,TP->Toasters[i].y))>=0)
  490.       {
  491.        if (ABS(TP->Toasters[j].old_x-TP->Toasters[i].old_x)<(IMAGE_WIDBUF))
  492.         {
  493.          if (TP->Toasters[i].y<TP->Toasters[j].y) TP->Toasters[i].ycol=j;
  494.          if (TP->Toasters[i].xspeed==TP->Toasters[j].xspeed) TP->Toasters[i].xspeed++;
  495.         }
  496.        else
  497.         {
  498.          if (TP->Toasters[i].x > TP->Toasters[j].x) TP->Toasters[i].xcol=j;
  499.          if (TP->Toasters[i].yspeed==TP->Toasters[j].yspeed) TP->Toasters[i].yspeed++;
  500.         }
  501.        if (ABS(TP->Toasters[j].old_y-TP->Toasters[i].old_y)<(IMAGE_HEIBUF))
  502.         {
  503.          if (TP->Toasters[i].x > TP->Toasters[j].x) TP->Toasters[i].xcol=j;
  504.          if (TP->Toasters[i].yspeed==TP->Toasters[j].yspeed) TP->Toasters[i].yspeed++;
  505.         }
  506.       }
  507.     }
  508.   }
  509.  
  510.  for (i=0; i<TP->NumToaster; i++)
  511.   {
  512.    if (TP->Toasters[i].delay==0L)
  513.     {
  514.      TP->Toasters[i].x=TP->Toasters[i].old_x-ActXSpeed(TP,i);
  515.      TP->Toasters[i].y=TP->Toasters[i].old_y + ActYSpeed(TP,i);
  516.     }
  517.   }
  518.           
  519.  for (i=0; i<TP->NumToaster; i++)
  520.   {
  521.    if (TP->Toasters[i].delay==0L)
  522.     {
  523.      j=-1;
  524.      while ((j=TestExtent(TP,j+1,i,TP->Toasters[i].x,TP->Toasters[i].y))>=0)
  525.       {
  526.        if (ABS(TP->Toasters[j].old_x-TP->Toasters[i].old_x)<(IMAGE_WIDBUF))
  527.         if (TP->Toasters[i].x > TP->Toasters[j].x) TP->Toasters[i].x=TP->Toasters[i].old_x;
  528.         else
  529.          if (TP->Toasters[i].y<TP->Toasters[j].y) TP->Toasters[i].y=TP->Toasters[i].old_y;
  530.  
  531.        if (ABS(TP->Toasters[j].old_y-TP->Toasters[i].old_y)<(IMAGE_HEIBUF))
  532.         if (TP->Toasters[i].y<TP->Toasters[j].y)
  533.          TP->Toasters[i].y=TP->Toasters[i].old_y;
  534.       }
  535.     }
  536.   }
  537.  
  538.  for (i=0; i<TP->NumToaster; i++)
  539.   if (TP->Toasters[i].delay==0L)
  540.    {
  541.     TP->Toasters[i].phase=(TP->Toasters[i].phase+1)%NUM_PHASES;
  542.  
  543.     SafeEraseRect (BTDDrawInfo,
  544.                    TP->Toasters[i].x+IMAGE_WIDTH,
  545.                    TP->Toasters[i].old_y,
  546.                    TP->Toasters[i].x+IMAGE_WIDTH+TP->Toasters[i].xspeed,
  547.                    TP->Toasters[i].old_y+IMAGE_HEIGHT);
  548.     SafeEraseRect (BTDDrawInfo,
  549.                    TP->Toasters[i].old_x,
  550.                    TP->Toasters[i].old_y,
  551.                    TP->Toasters[i].old_x+IMAGE_WIDTH,
  552.                    TP->Toasters[i].old_y+TP->Toasters[i].yspeed);
  553.  
  554.     DrawToasterImage (BTDDrawInfo,TP->Images[TP->Toasters[i].phase],
  555.                      TP->Toasters[i].x,TP->Toasters[i].y);
  556.  
  557.     if ((TP->Toasters[i].x<=(-IMAGE_WIDTH-1))||
  558.         (TP->Toasters[i].y>=TP->Height)) TP->Toasters[i].delay=Random(TP,50);
  559.    }
  560.   else
  561.    if (--TP->Toasters[i].delay==0L)
  562.     TP->Toasters[i].delay=FindLaunchPos(TP,i)?0:30;
  563.  
  564.  WaitTOF();
  565. }
  566.  
  567. ULONG PenCountMyBlanker(struct TagItem *TagList)
  568.  
  569. {
  570.  return NUM_COLORS-1L;
  571. }
  572.